#ifndef __K_AUTOFREEPTR_H__
#define __K_AUTOFREEPTR_H__

namespace kbase
{

template<class E>
struct _AutoFreePtrFree
{
	void operator()(E* p)
	{
		delete p;
	}
};

template <class E, class Releaser = _AutoFreePtrFree<E> >
class AutoFreePtr
{
protected:
	E* _ptr;
	Releaser _releaser;

public:
	AutoFreePtr()		  { _ptr = nullptr; }
	explicit AutoFreePtr(E* p)
	{
		_ptr = p;
	}
	// it had better not call this
	AutoFreePtr(const AutoFreePtr<E, Releaser>& p)
	{
		_ptr = p._ptr;
	}
	~AutoFreePtr()
	{
		_releaser(_ptr);
		_ptr = nullptr;
	}
	void attach(E* p)
	{
		if (_ptr)
			_releaser(_ptr);
		_ptr = p;
	}
	// not delete
	E* detach()
	{
		E* tmp = _ptr;
		_ptr = nullptr;
		return tmp;
	}
	void clear()
	{
		if (_ptr)
		{
			_releaser(_ptr);
			_ptr = nullptr;
		}
	}
	E* operator=(E* p)
	{
		attach(p);
		return _ptr;
	}
	E* operator=(const AutoFreePtr<E, Releaser>& p)
	{
		attach(p._ptr);
		return _ptr;
	}
	E& operator*() const
	{ return *_ptr; }
	operator E*() const
	{ return _ptr; }
	E** operator&() // The assert on operator& usually indicates a bug.
	{ return &_ptr; }
	E* operator->() const
	{ return _ptr; }
	bool operator!() const
	{ return _ptr == nullptr; }
	bool operator==(E* p) const
	{ return _ptr == p; }
	bool operator!=(E* p) const
	{ return _ptr != p; }
};

}

#endif // __K_AUTOFREEPTR_H__